import { RouteRecordRaw } from "vue-router";
import { defineStore } from "pinia";
import { constantRoutes } from "@/router";
import { store } from "@/store";
import { listRoutes } from "@/api/menu";
const modules = import.meta.glob("../../views/**/**.vue");
const Layout = () => import("@/layout/index.vue");

/**
 * @param roles 用户角色集合
 * @param route 路由
 * @returns
 */
const hasPermission = (roles: string[], route: RouteRecordRaw) => {
	// 角色【超级管理员】拥有所有权限，忽略校验
	if (roles.includes("ADMIN")) {
		return true;
	}
	return roles.some((role) => {
		if (route.meta?.roles !== undefined) {
			return (route.meta.roles as string[]).includes(role);
		}
	});
};

/**
 * 递归过滤有权限的异步(动态)路由
 *
 * @param routes 接口返回的异步(动态)路由
 * @param roles 用户角色集合
 * @returns 返回用户有权限的异步(动态)路由
 */
const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => {
	const asyncRoutes: RouteRecordRaw[] = [];

	routes.forEach((route) => {
		const tmpRoute = { ...route }; // ES6扩展运算符复制新对象
		if (!route.name) {
			tmpRoute.name = route.path;
		}
		// 判断用户(角色)是否有该路由的访问权限
		if (hasPermission(roles, tmpRoute)) {
			if (tmpRoute.component?.toString() == "Layout") {
				tmpRoute.component = Layout;
			} else {
				const component = modules[`../../views/${tmpRoute.component}.vue`];
				if (component) {
					tmpRoute.component = component;
				} else {
					tmpRoute.component = modules[`../../views/error-page/404.vue`];
				}
			}

			if (tmpRoute.children) {
				tmpRoute.children = filterAsyncRoutes(tmpRoute.children, roles);
			}

			asyncRoutes.push(tmpRoute);
		}
	});

	return asyncRoutes;
};

// setup
export const usePermissionStore = defineStore("permission", () => {
	// state
	const routes = ref<RouteRecordRaw[]>([]);

	/**
	 * 生成动态路由
	 *
	 * @param roles 用户角色集合
	 * @returns
	 */
	function generateRoutes(roles: string[]) {
		return new Promise<RouteRecordRaw[]>((resolve, reject) => {
			// 接口获取所有路由
			listRoutes()
				.then(({ data: asyncRoutes }) => {
					// 根据角色获取有访问权限的路由
					const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);
					// 添加静态路由和异步路由
					routes.value = constantRoutes.concat(accessedRoutes);

					resolve(accessedRoutes);
				})
				.catch((error) => {
					reject(error);
				});
		});
	}

	return { routes, generateRoutes };
});

// 非setup
export function usePermissionStoreHook() {
	return usePermissionStore(store);
}
